home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 05 - 1989 / 05.06 Jun 89 / LOC Source / Test Source / Test.p < prev    next >
Encoding:
Text File  |  1988-07-27  |  10.7 KB  |  504 lines  |  [TEXT/MPS ]

  1. (*****************************************************
  2. Test.p
  3.     List-of-Controls example, using pop-up menu
  4.     controls.
  5. *****************************************************)
  6.  
  7. PROGRAM Test;
  8.  
  9. USES
  10.     {$U MemTypes.p                }    MemTypes,
  11.     {$U QuickDraw.p               }    QuickDraw,
  12.     {$U OSIntf.p                      }    OSIntf,
  13.     {$U ToolIntf.p                    }    ToolIntf,
  14.     {$U PackIntf.p                    }    PackIntf,
  15.     {$U PopMenuIntf.p            }    PopMenuIntf;
  16.  
  17. CONST
  18.     RES_ID        = 128;        { resource ID's    }
  19.     
  20.     iOK                =    1;            { OK button            }
  21.     iLIST                =    2;            { list of controls    }
  22.     
  23.     { visibility }
  24.     isVIS                = 255;
  25.     notVIS            =   0;
  26.  
  27. TYPE
  28.     { Pascal equivalent of 'INT#' resource type }
  29.     IntList = record
  30.         count:        INTEGER;
  31.         int:                array[1..1024] of INTEGER;
  32.     end;  { IntList }
  33.     
  34.     ILPointer = ^IntList;
  35.     ILHandle = ^ILPointer;
  36.  
  37.  
  38. VAR
  39.     myDialog:    DialogPtr;    { test dialog            }
  40.     lh:                    ListHandle;    { handle to list        }
  41.     itemHit:        INTEGER;    { user's choice        }
  42.     savePort:    GrafPtr;        { to save port in        }
  43.  
  44.  
  45.  
  46.  
  47.  
  48. (*****************************************************
  49. CenterWindow:    Centers the given window in the
  50.     screen.  If the 'show' argument is TRUE, then the
  51.     window is shown.
  52. *****************************************************)
  53.  
  54. PROCEDURE CenterWindow(wPtr: WindowPtr;
  55.                                                         show: Boolean);
  56. VAR
  57.     pRect:        Rect;
  58.     wRect:        Rect;
  59.     h, v:        INTEGER;
  60.     
  61. BEGIN
  62.     pRect := screenBits.bounds;
  63.     wRect := WindowPeek(wPtr)^.port.portRect;
  64.     
  65.     v := ((pRect.bottom - pRect.top) -
  66.             (wRect.bottom - wRect.top)) div 3;
  67.     h := ((pRect.right - pRect.left) -
  68.             (wRect.right - wRect.left)) div 2;
  69.     
  70.     MoveWindow(wPtr, h, v, show);
  71.     
  72.     if (show) then begin
  73.         ShowWindow(wPtr);
  74.     end;
  75. END;  { CenterWindow }
  76.  
  77.  
  78.  
  79. (*****************************************************
  80. FixCtlRects:  Make the contrlRects of all controls in
  81.     the list match their list rectangles, and that controls
  82.     in invisible cells are also invisible.
  83. *****************************************************)
  84.  
  85. PROCEDURE FixCtlRects(lh: ListHandle);
  86. VAR
  87.     ch:                ControlHandle;
  88.     i:                    INTEGER;
  89.     dl:                INTEGER;
  90.     toRect:        Rect;
  91.     c:                Cell;
  92.     
  93. BEGIN
  94.     { default }
  95.     dl := sizeof(Handle);
  96.     
  97.     { update the controls in the list }
  98.     FOR i := 0 to (lh^^.dataBounds.bottom - 1) DO BEGIN
  99.         { define cell to access }
  100.         SetPt(Point(c), 0, i);
  101.         
  102.         { get the control handle from the cell }
  103.         LGetCell(@ch, dl, c, lh);
  104.         
  105.         IF (PtInRect(Point(c), lh^^.visible)) THEN
  106.             BEGIN
  107.                 { get cell rect; copy into control rect }
  108.                 LRect(toRect, c, lh);
  109.                 ch^^.contrlRect := toRect;
  110.                 
  111.                 { make sure the control is visible }
  112.                 ch^^.contrlVis := isVIS;
  113.             END
  114.         ELSE BEGIN
  115.             { make sure the control is invisible }
  116.             ch^^.contrlVis := notVIS;
  117.         END;
  118.     END;
  119. END;  { FixCtlRects }
  120.  
  121.  
  122.  
  123.  
  124. (*****************************************************
  125. FindCell:  Find the cell in the given list containing
  126.     the given point, which is assumed to be in local
  127.     coördinates.  If the point is not in the list's
  128.     rectangle, the resulting cell will have both
  129.     h and v set to (-1).
  130. *****************************************************)
  131.  
  132. FUNCTION FindCell(p: Point; lh: ListHandle): Cell;
  133. VAR
  134.     c:     Cell;
  135.  
  136. BEGIN
  137.     with lh^^ do begin
  138.         if (not PtInRect(p, rView)) then
  139.             SetPt(Point(c), -1, -1)
  140.         else with rView.topLeft do begin
  141.             c.h := ((p.h - h) DIV cellSize.h) + visible.left;
  142.             c.v := ((p.v - v) DIV cellSize.v) + visible.top;
  143.         end;  { else, with rView.topLeft }
  144.     end;  { with lh^^ }
  145.     
  146.     FindCell := c;
  147. END;  { FindCell }
  148.  
  149.  
  150.  
  151.  
  152. (*****************************************************
  153. doKeyDown:  Filters all keyDown events in the modal
  154.     dialog, implementing the standard keyboard
  155.     equivalents for the OK button.
  156. *****************************************************)
  157.  
  158. FUNCTION doKeyDown(dPtr: DialogPtr;
  159.                    VAR theEvent:  EventRecord;
  160.                    VAR itemHit: INTEGER): Boolean;
  161. VAR
  162.     c:        LONGINT;
  163.     
  164. BEGIN
  165.     { default }
  166.     doKeyDown := FALSE;
  167.     
  168.     { get the ascii code }
  169.     c := BitAnd(theEvent.message, charCodeMask);
  170.     
  171.     { check for Return or Enter }
  172.     IF ((c = 3) or ( c = 13)) THEN BEGIN
  173.         itemHit := iOK;
  174.         doKeyDown := TRUE;
  175.     END;  { if }
  176. END;  { doKeyDown }
  177.  
  178.  
  179.  
  180.  
  181. (*****************************************************
  182. doMouseDown
  183. *****************************************************)
  184.  
  185. FUNCTION doMouseDown(dPtr: DialogPtr;
  186.                      VAR theEvent:  EventRecord;
  187.                      VAR itemHit: INTEGER): Boolean;
  188. VAR
  189.     item:    INTEGER;
  190.     part:    INTEGER;
  191.     pt:        Point;
  192.     c:        Cell;
  193.     ch:        ControlHandle;
  194.     dbl:    Boolean;
  195.     sel:    Boolean;
  196.     
  197. BEGIN
  198.     pt := theEvent.where;
  199.     GlobalToLocal(pt);
  200.     
  201.     { See Tech Note #112, FindDItem() }
  202.     item := FindDItem(dPtr, pt) + 1;
  203.     
  204.     IF (item = iLIST) THEN
  205.         BEGIN
  206.             { in whom did the mouseDown occur? }
  207.             part := FindControl(pt, dPtr, ch);
  208.     
  209.             IF ((ch = nil) or (ch = lh^^.vScroll)) THEN
  210.                 BEGIN
  211.                     { clicked in list or in scroll bar }
  212.                     dbl := LClick(pt, theEvent.modifiers, lh);
  213.             
  214.                     { fix the controls' contrlRects }
  215.                     FixCtlRects(lh);
  216.                 END
  217.             ELSE BEGIN { clicked in pop-up menu }
  218.                 part := TrackControl(ch, pt, POINTER(-1));
  219.                 
  220.                 { what cell was the mouseDown in? }
  221.                 c := FindCell(pt, lh);
  222.                 
  223.                 { redraw the control if cell was selected }
  224.                 if (LGetSelect(false, c, lh)) then begin
  225.                     HiliteControl(ch, titlePart);
  226.                 end;  { if }
  227.             END;  { else }
  228.             
  229.             doMouseDown := TRUE;
  230.         END  { item = iLIST }
  231.     ELSE BEGIN
  232.         doMouseDown := FALSE;
  233.     END;
  234. END;  { doMouseDown }
  235.  
  236.  
  237.  
  238.  
  239. (*****************************************************
  240. doUpdateEvt
  241. *****************************************************)
  242.  
  243. FUNCTION doUpdateEvt(dPtr: DialogPtr;
  244.                    VAR theEvent:  EventRecord;
  245.                    VAR itemHit: INTEGER): Boolean;
  246. BEGIN
  247.     { begin the update }
  248.     BeginUpdate(dPtr);
  249.     
  250.     { update the dialog items }
  251.     UpdtDialog(dPtr, dPtr^.visRgn);
  252.     
  253.     { update the list }
  254.     LUpdate(dPtr^.visRgn, lh);
  255.     
  256.     { end the update } 
  257.     EndUpdate(dPtr);
  258.     
  259.     { always return true (we handled it) }
  260.     doUpdateEvt := TRUE;
  261. END;  { doUpdateEvt }
  262.  
  263.  
  264.  
  265.  
  266. (*****************************************************
  267. MyFilter
  268. *****************************************************)
  269.  
  270. FUNCTION MyFilter(dPtr: DialogPtr;
  271.                   VAR theEvent:  EventRecord;
  272.                   VAR itemHit: INTEGER): Boolean;
  273. BEGIN
  274.     CASE theEvent.what OF
  275.         keyDown:
  276.             MyFilter := doKeyDown(dPtr, theEvent, itemHit);
  277.         mouseDown:
  278.             MyFilter := doMouseDown(dPtr, theEvent, itemHit);
  279.         updateEvt:
  280.             MyFilter := doUpdateEvt(dPtr, theEvent, itemHit);
  281.         OTHERWISE
  282.             MyFilter := FALSE;
  283.     END;  { case }
  284. END;  { MyFilter }
  285.     
  286.     
  287.     
  288.  
  289.  
  290. (*****************************************************
  291. DrawUserItems
  292. *****************************************************)
  293.  
  294. PROCEDURE DrawUserItems(wPtr: WindowPtr;
  295.                 itemNo: INTEGER);
  296. VAR
  297.     savePen:        PenState;
  298.     ik:                INTEGER;
  299.     ih:                Handle;
  300.     ib:                Rect;
  301.     
  302. BEGIN    { DrawUserItems }
  303.     { save, naormalize the pen state }
  304.     GetPenState(savePen);
  305.     PenNormal;
  306.     
  307.     { frame the list }
  308.     GetDItem(wPtr, iLIST, ik, ih, ib);
  309.     FrameRect(ib);
  310.     
  311.     { frame the default button }
  312.     GetDItem(wPtr, iOK, ik, ih, ib);
  313.     InsetRect(ib, -4, -4);
  314.     PenSize(3, 3);
  315.     FrameRoundRect(ib, 16, 16);
  316.                 
  317.     { restore the pen's state }
  318.     SetPenState(savePen);
  319. END;    { DrawUserItems }
  320.  
  321.  
  322.  
  323.  
  324. (*****************************************************
  325. ReadData: Reads in a number of controls, as specified
  326.     by a 'INT#' integer-array resource.  Defines new
  327.     controls for each.
  328. *****************************************************)
  329.  
  330. FUNCTION ReadData(dPtr: DialogPtr): Boolean;
  331. VAR
  332.     ch:                ControlHandle;
  333.     iah:            ILHandle;
  334.     i:                INTEGER;
  335.     n:                INTEGER;
  336.     ignore:            INTEGER;
  337.     aCell:            Cell;
  338.     p:                Point;
  339.     aRect:            Rect;
  340.     
  341. BEGIN    { ReadData }
  342.     { get handle to 'INT#' resource }
  343.     iah := ILHandle(GetResource('INT#', RES_ID));
  344.     
  345.     IF (iah <> nil) THEN BEGIN
  346.         { disable list drawing }
  347.         LDoDraw(false, lh);
  348.             
  349.         FOR i := 1 TO iah^^.count DO BEGIN
  350.             { create a new control  }
  351.             ch := GetNewControl(iah^^.int[i], dPtr);
  352.             
  353.             IF (ch = nil) THEN LEAVE;
  354.             
  355.             { make the control visible, without drawing }
  356.             ch^^.contrlVis := 255;
  357.             
  358.             ignore := LAddRow(1, 32767, lh);
  359.             SetPt(Point(aCell), 0, i - 1);
  360.             LSetCell(@ch, sizeof(Handle), aCell, lh);
  361.         END;  { for }
  362.             
  363.         { fix the controls' contrlRects }
  364.         FixCtlRects(lh);
  365.         
  366.         { select first control }
  367.         SetPt(Point(aCell), 0, 0);
  368.         LSetSelect(true, aCell, lh);
  369.         
  370.         { enable list drawing }
  371.         LDoDraw(true, lh);    
  372.     END;  { iah <> nil }
  373.     
  374.     { return TRUE if controls were read iOK }
  375.     ReadData := (iah <> nil);
  376. END;  { ReadData }
  377.  
  378.  
  379.  
  380.  
  381. (*****************************************************
  382. InitList:  Define and allocate new list, into which
  383.     will be placed a number of control handles.
  384.     (See ReadData(), above.)
  385. *****************************************************)
  386. PROCEDURE InitList(dPtr: DialogPtr);
  387. VAR
  388.     ik:            INTEGER;
  389.     ih:            Handle;
  390.     ib:            Rect;
  391.     dBounds:    Rect;
  392.     cSize:        Point;
  393.     
  394. BEGIN
  395.     { set up the userItem drawing routine }
  396.     GetDItem(dPtr, iLIST, ik, ih, ib);
  397.     SetDItem(dPtr, iLIST, ik, Handle(@DrawUserItems), ib);
  398.     
  399.     { inset rect, for drawing; leave room for scroll bar }
  400.     InsetRect(ib, 1, 1);
  401.     ib.right := ib.right - 15;
  402.     
  403.     { allocate space for a single column, no rows }
  404.     SetRect(dBounds, 0, 0, 1, 0);
  405.     
  406.     { indicate cell size }
  407.     SetPt(cSize, ib.right-ib.left, 20);
  408.     
  409.     { create the list }
  410.     lh := LNew(
  411.                                 ib,          { rView        }
  412.                                 dBounds,  { dataBounds    }
  413.                                 cSize,      { cell size    }
  414.                                 RES_ID,   { resource ID    }
  415.                                 dPtr,      { this window    }
  416.                                 false,      { draw it        }
  417.                                 false,      { grow box    }
  418.                                 false,      { sBar, horiz    }
  419.                                 true);      { sBar, vert    }
  420. END;  { InitList }
  421.  
  422.  
  423.  
  424.  
  425. (*****************************************************
  426. CleanUp:  My name is CleanUp().  You killed my dialog.
  427.     Prepare to die!
  428. *****************************************************)
  429.  
  430. PROCEDURE CleanUp(dPtr: DialogPtr);
  431. VAR
  432.     ch:        ControlHandle;
  433.     i:        INTEGER;
  434.     dl:        INTEGER;
  435.     c:        Cell;
  436.     
  437. BEGIN
  438.     { default }
  439.     dl := sizeof(Handle);
  440.     
  441.     { indicate wait }
  442.     SetCursor(GetCursor(watchCursor)^^);
  443.     
  444.     { deallocate the controls from the list }
  445.     FOR i := 0 to (lh^^.dataBounds.bottom - 1) DO BEGIN
  446.         SetPt(Point(c), 0, i);
  447.         LGetCell(@ch, dl, c, lh);
  448.         
  449.         DisposeControl(ch);
  450.     END;  { for }
  451.     
  452.     { dispose of the list }
  453.     LDispose(lh);
  454.     
  455.     { dispose of the dialog }
  456.     DisposDialog(dPtr);
  457. END;  { CleanUp }
  458.  
  459.  
  460.  
  461.  
  462.  
  463. (*****************************************************
  464. Main
  465. *****************************************************)
  466.  
  467. BEGIN
  468.     { perform the ritual incantation }
  469.     InitGraf(@thePort);    
  470.     InitFonts;            
  471.     FlushEvents(everyEvent, 0);
  472.     InitWindows;                
  473.     InitMenus;            
  474.     TEInit;
  475.     InitDialogs(NIL);            
  476.     InitCursor;
  477.  
  478.     { read in the dialog from its resource template }
  479.     myDialog := GetNewDialog(RES_ID, NIL,
  480.                                 POINTER(-1));
  481.     
  482.     { create and init the list of controls }
  483.     InitList(myDialog);
  484.     
  485.     IF (ReadData(myDialog)) THEN BEGIN
  486.         { center and show the dialog }
  487.         CenterWindow(myDialog, true);
  488.         
  489.         { save grafPort, make ours current }
  490.         GetPort(savePort);
  491.         SetPort(myDialog);
  492.         
  493.         { cycle through ModalDialog() }
  494.         REPEAT
  495.             ModalDialog(@MyFilter, itemHit);
  496.         UNTIL itemHit = iOK;
  497.         
  498.         { restore grafPort }
  499.         SetPort(savePort);
  500.     END;
  501.     
  502.     { dispose of the dialog's storage }
  503.     CleanUp(myDialog);
  504. END.  { FILE Test.p, PROGRAM Test.p }